package com.xmall.auth.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xmall.auth.dao.*;
import com.xmall.auth.entity.*;
import com.xmall.auth.service.ISysRoleService;
import com.xmall.auth.service.ISysUserService;
import com.xmall.auth.service.XmallUserDetailsService;
import com.xmall.auth.xmallauth.jwt.model.LoginUser;
import com.xmall.auth.xmallauth.jwt.util.JwtTokenUtil;
import com.xmall.common.config.PlatformContant;
import com.xmall.common.config.PojoUtils;
import com.xmall.common.model.JwtUser;
import com.xmall.common.model.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author liuzh
 * @since 2020-05-16
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    @Autowired
    private XmallUserDetailsService xmallUserDetailsService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Value("${jwt.tokenHeader}")
    private String tokenHeader;
    @Value("${jwt.tokenPrefix}")
    private String tokenPrefix;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private SysRolePermissionRelationMapper sysRolePermissionRelationMapper;
    @Autowired
    private SysRoleMenuRelationMapper sysRoleMenuRelationMapper;
    @Autowired
    private SysRoleResourceRelationMapper sysRoleResourceRelationMapper;

    @Autowired
    private SysAdminPermissionRelationMapper sysAdminPermissionRelationMapper;
    @Autowired
    private SysAdminRoleRelationMapper sysAdminRoleRelationMapper;
    @Autowired
    private ISysRoleService sysRoleService;

    @Override
    public boolean registerUser(SysUser sysUser) {
        sysUser.setUserPassword(passwordEncoder.encode(sysUser.getUserPassword()));
        PojoUtils.setSysProperties(sysUser, PlatformContant.OpType.insert);
        return save(sysUser);
    }

    @Override
    public boolean updateUser(SysUser sysUser, LambdaQueryWrapper<SysUser> queryWrapper) {
        if (!StrUtil.isEmpty(sysUser.getUserPassword())) {
            sysUser.setUserPassword(passwordEncoder.encode(sysUser.getUserPassword()));
        }
        PojoUtils.setSysProperties(sysUser, PlatformContant.OpType.update);
        boolean update = update(
                sysUser,
                new QueryWrapper<SysUser>()
                        .lambda().eq(SysUser::getId, sysUser.getId())
        );
        return update;
    }

    @Override
    public boolean deleteUser(Long id) {
        boolean b = removeById(id);
        return b;
    }

    @Override
    public Map<String, String> login(LoginUser loginUser) {
        String token = null;
        //密码需要客户端加密后传递
        UserDetails userDetails = xmallUserDetailsService.loadUserByUsername(loginUser.getUsername());
        if (userDetails == null) {
            throw new BadCredentialsException("密码不正确");
        }
        if (!passwordEncoder.matches(loginUser.getPassword(), userDetails.getPassword())) {
            throw new BadCredentialsException("密码不正确");
        }
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
        token = jwtTokenUtil.generateToken(userDetails);


        SysUser sysUser = getById(((JwtUser) userDetails).getId());
        sysUser.setLoginTime(new Date());
        updateById(sysUser);

        Map<String, String> tokenMap = new HashMap<>();
        tokenMap.put("token", token);
        tokenMap.put("tokenPrefix", tokenPrefix);
        return tokenMap;
    }

    @Override
    public Map<String, Object> getAdminInfo(String userName) {
        JwtUser jwtUser = xmallUserDetailsService.loadUserByUsername(userName);
        Map<String, Object> data = new HashMap<>();
        data.put("id", jwtUser.getId());
        data.put("username", jwtUser.getUsername());
        data.put("roles", new String[]{"TEST"});
        Long adminId = Long.parseLong(jwtUser.getId());
        data.put("menus", sysRoleService.getMenuList(adminId));
//        JwtUser jwtUser = xmallUserDetailsService.loadUserByUsername(username);
//        Map<String, Object> data = new HashMap<>();
//        data.put("username", jwtUser.getUsername());
//        data.put("roles", new String[]{"TEST"});
        // data.put("menus", roleService.getMenuList(umsAdmin.getId()));
        //  data.put("icon", umsAdmin.getIcon());
        return data;
    }


    @Override
    public int updateRole(Long adminId, List<Long> roleIds) {
        int count = roleIds == null ? 0 : roleIds.size();
        //先删除原来的关系
        sysAdminRoleRelationMapper.delete(new QueryWrapper<SysAdminRoleRelation>().lambda().eq(SysAdminRoleRelation::getAdminId, adminId));

        //建立新关系
        if (!CollectionUtils.isEmpty(roleIds)) {
            for (Long roleId : roleIds) {
                SysAdminRoleRelation roleRelation = new SysAdminRoleRelation();
                roleRelation.setAdminId(adminId);
                roleRelation.setRoleId(roleId);
                PojoUtils.setSysProperties(roleRelation, PlatformContant.OpType.insert);
                sysAdminRoleRelationMapper.insert(roleRelation);
            }
        }
        return count;
    }

    @Override
    public List<SysRole> getRoleList(Long adminId) {
        return sysAdminRoleRelationMapper.getRoleList(adminId);
    }

    @Override
    public List<SysResource> getResourceList(Long adminId) {
        return sysAdminRoleRelationMapper.getResourceList(adminId);
    }

    @Override
    public int updatePermission(Long adminId, List<Long> permissionIds) {
        //删除原所有权限关系
        sysAdminPermissionRelationMapper.delete(new QueryWrapper<SysAdminPermissionRelation>().lambda().eq(SysAdminPermissionRelation::getAdminId, adminId));
        //获取用户所有角色权限
        List<SysPermission> permissionList = sysAdminRoleRelationMapper.getRolePermissionList(adminId);
        List<Long> rolePermissionList = permissionList.stream().map(SysPermission::getId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(permissionIds)) {
            List<SysAdminPermissionRelation> relationList = new ArrayList<>();
            //筛选出+权限
            List<Long> addPermissionIdList = permissionIds.stream().filter(permissionId -> !rolePermissionList.contains(permissionId)).collect(Collectors.toList());
            //筛选出-权限
            List<Long> subPermissionIdList = rolePermissionList.stream().filter(permissionId -> !permissionIds.contains(permissionId)).collect(Collectors.toList());
            //插入+-权限关系
            relationList.addAll(convert(adminId, 1, addPermissionIdList));
            relationList.addAll(convert(adminId, -1, subPermissionIdList));

            relationList.stream().forEach(sysAdminPermissionRelation -> sysAdminPermissionRelationMapper.insert(sysAdminPermissionRelation));
        }
        return 0;
    }

    /**
     * 将+-权限关系转化为对象
     */
    private List<SysAdminPermissionRelation> convert(Long adminId, Integer type, List<Long> permissionIdList) {
        List<SysAdminPermissionRelation> relationList = permissionIdList.stream().map(permissionId -> {
            SysAdminPermissionRelation relation = new SysAdminPermissionRelation();
            relation.setAdminId(adminId);
            relation.setType(type);
            relation.setPermissionId(permissionId);
            PojoUtils.setSysProperties(relation, PlatformContant.OpType.insert);
            return relation;
        }).collect(Collectors.toList());
        return relationList;
    }

    @Override
    public List<SysPermission> getPermissionList(Long adminId) {
        return sysAdminRoleRelationMapper.getPermissionList(adminId);
    }
}
